
import javax.sip.*;
import javax.sip.address.Address;
import javax.sip.header.HeaderFactory;
import javax.sip.message.Message;
import java.util.*;
public class Example implements SipListener {
	private SipFactory sipFactory = null;
	private Address addressFactory = null;
	private HeaderFactory headerFactory = null;
	private Message messageFactory = null;
	private SipStack sipStack = null;
	private SipProvider sipProvider = null;
	private Iterator listeningPoints = null;
	// Main
	public static void main(String[] args) {
		Example example = new Example();
		example.sendMessages();
	}
	public Example() {
		setup();
	}
	private void setup() {
		// Obtain an instance of the singleton SipFactory
		sipFactory = SipFactory.getInstance();
		// Set path name of SipFactory to reference implementation
		// (not needed - default path name)
		sipFactory.setPathName("com.dynamicsoft.ri");
		try {
			// Create SipStack object
			sipStack = (SipStack)sipFactory.createSipStack();
		} catch(SipPeerUnavailableException e) {
			// could not find com.dynamicsoft.ri.jain.protocol.ip.sip.SipStackImpl
			// in the classpath
			System.err.println(e.getMessage());
			System.exit(-1);
		} catch(SipException e) {
			// could not create SipStack for some other reason
			System.err.println(e.getMessage());
			System.exit(-1);
		}
		// Set name of SipStack
		sipStack.setStackName("Reference Implementation SIP stack");
		try {
			// Get SipStack's ListeningPoints
			listeningPoints = sipStack.getListeningPoints();
			// Create SipProvider based on the first ListeningPoint
			sipProvider = sipStack.createSipProvider((ListeningPoint)listeningPoints.next());
		} catch(NullPointerException e) {
			System.err.println("Stack has no ListeningPoints");
			System.exit(-1);
		} catch(ListeningPointUnavailableException e) {
			System.err.println(e.getMessage());
			System.exit(-1);
		}
		// Register this application as a SipListener of the SipProvider
		try {
			sipProvider.addSipListener(this);
		} catch(TooManyListenersException e) {
			// A limit has been reached on the number of Listeners allowed per provider
			System.err.println(e.getMessage());
			System.exit(-1);
		} catch(SipListenerAlreadyRegisteredException e) {
			// Already been added as SipListener
			System.err.println(e.getMessage());
			System.exit(-1);
		}
	}
	// Process transaction timeout
	public void processTimeOut(jain.protocol.ip.sip.SipEvent transactionTimeOutEvent) {
		if(transactionTimeOutEvent.isServerTransaction()) {
			System.out.println("Server transaction " + transactionTimeOutEvent.getTransactionId() + " timed out");
		} else {
			System.out.println("Client transaction " + transactionTimeOutEvent.getTransactionId() + " timed out");
		}
	}
	// Process Request received
	public void processRequest(jain.protocol.ip.sip.SipEvent requestReceivedEvent) {
		Request request = (Request)requestReceivedEvent.getMessage();
		long serverTransactionId = requestReceivedEvent.getTransactionId();
		System.out.println("\n\nRequest received with server transaction id " + serverTransactionId + ":\n" + request);
		try {
			// If request is not an ACK then try to send an OK Response
			if((!Request.ACK.equals(request.getMethod())) && (!Request.REGISTER.equals(request.getMethod()))) {
				sipProvider.sendResponse(serverTransactionId, Response.OK, "SDP body of Response", "application", "sdp");
			}
		} catch(TransactionDoesNotExistException e) {
			System.out.println(e.getMessage());
			System.exit(-1);
		} catch(SipParseException e) {
			System.out.println(e.getMessage());
			System.exit(-1);
		} catch(SipException e) {
			System.out.println(e.getMessage());
			System.exit(-1);
		}
	}
	// Process Response received
	public void processResponse(jain.protocol.ip.sip.SipEvent responseReceivedEvent) {
		Response response = (Response)responseReceivedEvent.getMessage();
		long clientTransactionId = responseReceivedEvent.getTransactionId();
		System.out.println("Response received with client transaction id " + clientTransactionId + ":\n" + response);
		try {
			// Get method of response
			String method = response.getCSeqHeader().getMethod();
			// Get status code of response
			int statusCode = response.getStatusCode();
			// If response is a 200 INVITE response, try to send an ACK
			if((statusCode == Response.OK) && (method.equals(Request.INVITE))) {
				sipProvider.sendAck(clientTransactionId);
			}
		} catch(SipException e) {
			System.err.println(e.getMessage());
			System.exit(-1);
		}
	}
	public void sendMessages() {
		try {
			// Create AddressFactory
			addressFactory = sipFactory.createAddressFactory();
			// Create HeaderFactory
			headerFactory = sipFactory.createHeaderFactory();
			// Create MessageFactory
			messageFactory = sipFactory.createMessageFactory();
		} catch(SipPeerUnavailableException e) {
			System.err.println(e.getMessage());
			System.exit(-1);
		}
		SipURL fromAddress = null;
		NameAddress fromNameAddress = null;
		FromHeader fromHeader = null;
		SipURL toAddress = null;
		NameAddress toNameAddress = null;
		ToHeader toHeader = null;
		SipURL requestURI = null;
		CallIdHeader callIdHeader = null;
		CSeqHeader cSeqHeader = null;
		ViaHeader viaHeader = null;
		ArrayList viaHeaders = null;
		ContentTypeHeader contentTypeHeader = null;
		Request invite = null;
		Request options = null;
		Request register = null;
		try {
			// create From Header
			fromAddress = addressFactory.createSipURL("caller", sipProvider.getListeningPoint().getHost());
			fromAddress.setPort(sipProvider.getListeningPoint().getPort());
			fromNameAddress = addressFactory.createNameAddress("Caller", fromAddress);
			fromHeader = headerFactory.createFromHeader(fromNameAddress);
			// create To Header
			toAddress = addressFactory.createSipURL("callee", sipProvider.getListeningPoint().getHost());
			toAddress.setPort(sipProvider.getListeningPoint().getPort());
			toNameAddress = addressFactory.createNameAddress("Callee", toAddress);
			toHeader = headerFactory.createToHeader(toNameAddress);
			// create Request URI
			requestURI = (SipURL)toAddress.clone();
			requestURI.setTransport(sipProvider.getListeningPoint().getTransport());
			// Create ViaHeaders
			String transport = sipProvider.getListeningPoint().getTransport();
			if(transport.equals(ListeningPoint.TRANSPORT_UDP)) {
				transport = ViaHeader.UDP;
			} else if(transport.equals(ListeningPoint.TRANSPORT_TCP)) {
				transport = ViaHeader.TCP;
			}
			viaHeader = headerFactory.createViaHeader(sipProvider.getListeningPoint().getHost(), sipProvider.getListeningPoint().getPort(), transport);
			viaHeaders = new ArrayList();
			viaHeaders.add(viaHeader);
			// Create ContentTypeHeader
			contentTypeHeader = headerFactory.createContentTypeHeader("application", "sdp");
			// Create and send INVITE Request
			callIdHeader = sipProvider.getNewCallIdHeader();
			cSeqHeader = headerFactory.createCSeqHeader(1, Request.INVITE);
			invite = messageFactory.createRequest(requestURI, Request.INVITE, callIdHeader, cSeqHeader, fromHeader, toHeader, viaHeaders, "SDP body of INVITE Request", contentTypeHeader);
			sipProvider.sendRequest(invite);
			// Create and send OPTIONS Request
			callIdHeader = sipProvider.getNewCallIdHeader();
			cSeqHeader = headerFactory.createCSeqHeader(1, Request.OPTIONS);
			options = messageFactory.createRequest(requestURI, Request.OPTIONS, callIdHeader, cSeqHeader, fromHeader, toHeader, viaHeaders, "SDP body of OPTIONS Request", contentTypeHeader);
			sipProvider.sendRequest(options);
			// Create and send REGISTER Request
			callIdHeader = sipProvider.getNewCallIdHeader();
			cSeqHeader = headerFactory.createCSeqHeader(1, Request.REGISTER);
			register = messageFactory.createRequest(requestURI, Request.REGISTER, callIdHeader, cSeqHeader, fromHeader, toHeader, viaHeaders, "SDP body of OPTIONS Request", contentTypeHeader);
			long clientTransactionId = sipProvider.sendRequest(register);
			// send CANCEL Request
			sipProvider.sendCancel(clientTransactionId);
			// send BYE Request
			sipProvider.sendBye(clientTransactionId, true);
		} catch(SipParseException e) {
			// Implementation was unable to parse a value
			System.err.println(e.getMessage() + "[" + e.getUnparsable() + "]");
			System.exit(-1);
		} catch(SipException e) {
			// Another exception occurred
			System.err.println(e.getMessage());
			System.exit(-1);
		}
	}
	@Override
	public void processDialogTerminated(DialogTerminatedEvent arg0) {
		// TODO Auto-generated method stub
	}
	@Override
	public void processIOException(IOExceptionEvent arg0) {
		// TODO Auto-generated method stub
	}
	@Override
	public void processRequest(RequestEvent arg0) {
		// TODO Auto-generated method stub
	}
	@Override
	public void processResponse(ResponseEvent arg0) {
		// TODO Auto-generated method stub
	}
	@Override
	public void processTimeout(TimeoutEvent arg0) {
		// TODO Auto-generated method stub
	}
	@Override
	public void processTransactionTerminated(TransactionTerminatedEvent arg0) {
		// TODO Auto-generated method stub
	}
}